package top.huanyv.tools.bean;

import top.huanyv.tools.utils.IoUtil;

import java.io.*;
import java.math.BigInteger;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;

public class Digest {

    public static final String MD5 = "MD5";
    public static final String SHA = "SHA-1";
    public static final String SHA_224 = "SHA-224";
    public static final String SHA_256 = "SHA-256";
    public static final String SHA_384 = "SHA-384";
    public static final String SHA_512 = "SHA-512";

    private MessageDigest digest;

    public Digest(String algorithm) {
        try {
            this.digest = MessageDigest.getInstance(algorithm);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
    }

    public Digest(String data, String algorithm) {
        this(data.getBytes(StandardCharsets.UTF_8), algorithm);
    }

    public Digest(byte[] data, String algorithm) {
        try {
            this.digest = MessageDigest.getInstance(algorithm);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        this.digest.update(data);
    }

    public void update(byte input) {
        this.digest.update(input);
    }

    public void update(byte[] input) {
        this.digest.update(input);
    }

    public void update(byte[] input, int offset, int len) {
        this.digest.update(input, offset, len);
    }

    public static String md5Digest(String data) {
        return new Digest(data.getBytes(StandardCharsets.UTF_8), MD5).toString();
    }

    public static String shaDigest(String data) {
        return new Digest(data.getBytes(StandardCharsets.UTF_8), SHA).toString();
    }

    public static String fileDigest(File file, String algorithm) {
        MessageDigest md = null;
        try {
            md = MessageDigest.getInstance(algorithm);
            fileDigest(file, md);
            return new BigInteger(1, md.digest()).toString(16);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void fileDigest(File file, MessageDigest digest) {
        BufferedInputStream bis = null;
        try {
            bis = new BufferedInputStream(new FileInputStream(file));
            byte[] buffer = new byte[1024];
            int len = -1;
            while ((len = bis.read(buffer, 0, 1024)) != -1) {
                digest.update(buffer, 0, len);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            IoUtil.close(bis);
        }
    }


    public static String pathDigest(File file, String algorithm) {
        try {
            MessageDigest digest = MessageDigest.getInstance(algorithm);
            pathDigest(file, digest);
            return new BigInteger(1, digest.digest()).toString(16);
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        }
        return null;
    }

    /**
     * 对文件夹下的所有文件进行摘要算法
     *
     * @param file 文件夹路径
     * @return {@link String}
     */
    public static void pathDigest(File file, MessageDigest digest) {
        File[] files = file.listFiles();
        if (files == null) {
            return;
        }
        for (File f : files) {
            if (f.isFile()) {
                fileDigest(f, digest);
            }
            if (f.isDirectory()) {
                pathDigest(f, digest);
            }
        }
    }


    @Override
    public String toString() {
        return new BigInteger(1, this.digest.digest()).toString(16);
    }
}
